package com.evil.application.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.evil.application.enums.form.control.ControlCodeEnum;
import com.evil.application.mapper.ApplicationFilterGroupMapper;
import com.evil.application.pojo.dto.view.config.filter.*;
import com.evil.application.pojo.dto.view.config.filter.query.FilterGroupQueryReqDTO;
import com.evil.application.pojo.entity.ApplicationFilterGroup;
import com.evil.application.pojo.entity.ApplicationFilterItem;
import com.evil.application.service.ApplicationFilterGroupService;
import com.evil.application.service.ApplicationFilterItemService;
import com.evil.application.util.OrderDataUtil;
import com.evil.common.application.dto.judge.JudgeAnd;
import com.evil.common.application.dto.judge.JudgeOr;
import com.evil.common.core.enums.RCodeEnum;
import com.evil.common.core.enums.SpecialFieldEnum;
import com.evil.common.core.enums.SwitchEnum;
import com.evil.common.core.exception.BusinessException;
import com.evil.common.core.util.StreamUtil;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 应用筛选组表
 *
 * @author liyang
 * @date 2022-08-08 00:00
 */
@Slf4j
@Service
@AllArgsConstructor
public class ApplicationFilterGroupServiceImpl extends ServiceImpl<ApplicationFilterGroupMapper, ApplicationFilterGroup> implements ApplicationFilterGroupService {

    private final ApplicationFilterItemService applicationFilterItemService;

    private final ApplicationLogServiceImpl logService;

    /**
     * 保存应用筛选
     *
     * @param modifyFilterReqDTO modifyFilterReqDTO
     */
    @Override
    public void saveFilter(ModifyFilterReqDTO modifyFilterReqDTO) {
        Map<Long, ApplicationFilterGroup> filterGroupMap = this.baseMapper.findMapBySource(modifyFilterReqDTO);

        List<Long> modifyIds = new ArrayList<>();

        // 新增/编辑
        modifyFilterReqDTO.getFilters().forEach(g -> {
            ApplicationFilterGroup group;
            if (Objects.nonNull(g.getFilterGroupId())) {
                if (!filterGroupMap.containsKey(g.getFilterGroupId())) {
                    throw new BusinessException(RCodeEnum.APPLICATION_FILTER_GROUP_NOT_EXIST);
                }
                group = filterGroupMap.get(g.getFilterGroupId());
                modifyIds.add(group.getFilterGroupId());
            } else {
                group = new ApplicationFilterGroup();
                group.setEnterpriseId(modifyFilterReqDTO.getEnterpriseId());
                group.setSourceId(modifyFilterReqDTO.getSourceId());
                group.setSourceType(modifyFilterReqDTO.getSourceType());
            }
            group.setFilterGroupName(g.getFilterGroupName());
            logService.saveAndCheck(this.baseMapper, ApplicationFilterGroup::getFilterGroupId, group);

            // 保存筛选项
            applicationFilterItemService.saveFilterItem(group, g.getFilterGroupConfig());
        });

        // 删除
        List<ApplicationFilterGroup> deletedList = StreamUtil.peekF(filterGroupMap.values(),
                i -> !modifyIds.contains(i.getFilterGroupId()), i -> i.setIsDeleted(SwitchEnum.YES.getId()));

        logService.save(this.baseMapper, ApplicationFilterGroup::getFilterGroupId, deletedList);
    }

    /**
     * 复制应用筛选
     *
     * @param copyFilterReqDTO copyFilterReqDTO
     */
    @Override
    public void copyFilter(CopyFilterReqDTO copyFilterReqDTO) {
        Long enterpriseId = copyFilterReqDTO.getEnterpriseId();
        FilterSourceDTO source = copyFilterReqDTO.getSource();
        FilterSourceDTO target = copyFilterReqDTO.getTarget();
        Boolean updateSource = copyFilterReqDTO.getUpdateSource();

        Map<Long, ApplicationFilterGroup> sourceGroupMap = this.baseMapper.findMapBySource(source);
        Map<Long, ApplicationFilterGroup> targetGroupMap = this.baseMapper.findMapBySource(target);

        List<Long> groupModifyIds = new ArrayList<>();
        // 新增/编辑
        sourceGroupMap.forEach((id, group) -> {
            ApplicationFilterGroup copyGroup;
            // 需要更新源信息并且对应有值
            if (updateSource && targetGroupMap.containsKey(group.getSourceGroupId())) {
                copyGroup = targetGroupMap.get(group.getSourceGroupId());
                copyGroup.setFilterGroupName(group.getFilterGroupName());

                groupModifyIds.add(group.getSourceGroupId());
            } else {
                copyGroup = BeanUtil.copyProperties(group, ApplicationFilterGroup.class, SpecialFieldEnum.getSpecialFields());
                copyGroup.setFilterGroupId(null);
                copyGroup.setEnterpriseId(enterpriseId);
                copyGroup.setSourceId(target.getSourceId());
                copyGroup.setSourceType(target.getSourceType());

                // 如果需要更新源信息：新的 需要映射上 复制源ID
                if (updateSource) {
                    copyGroup.setSourceGroupId(id);
                }
            }

            logService.saveAndCheck(this.baseMapper, ApplicationFilterGroup::getFilterGroupId, copyGroup);

            // 如果需要更新源信息：复制源 需要映射上 新ID
            if (updateSource) {
                group.setSourceGroupId(copyGroup.getFilterGroupId());
                logService.saveAndCheck(this.baseMapper, ApplicationFilterGroup::getFilterGroupId, group);
            }

            // 复制筛选项
            applicationFilterItemService.copyFilterItem(group, copyGroup, updateSource);
        });

        // 删除
        List<ApplicationFilterGroup> deleteList = StreamUtil.peekF(targetGroupMap.values(),
                g -> !groupModifyIds.contains(g.getFilterGroupId()), g -> g.setIsDeleted(SwitchEnum.YES.getId()));
        logService.saveAndCheck(this.baseMapper, ApplicationFilterGroup::getFilterGroupId, deleteList);
    }

    /**
     * 删除应用筛选
     *
     * @param filterSourceDTO filterSourceDTO
     */
    @Override
    public void deleteBySource(FilterSourceDTO filterSourceDTO) {
        Map<Long, ApplicationFilterGroup> groupMap = this.baseMapper.findMapBySource(filterSourceDTO);
        List<ApplicationFilterGroup> groupDeleted = StreamUtil.peek(groupMap.values(), e -> e.setIsDeleted(SwitchEnum.YES.getId()));
        logService.saveAndCheck(this.baseMapper, ApplicationFilterGroup::getFilterGroupId, groupDeleted);

        // 删除筛选项
        applicationFilterItemService.deleteFilterItem(groupMap.keySet());
    }

    /**
     * 获取应用筛选数据
     *
     * @param filterSourceDTO filterSourceDTO
     * @return List
     */
    @Override
    public List<FilterGroupDTO> findBySource(FilterSourceDTO filterSourceDTO) {
        Map<Long, ApplicationFilterGroup> groupMap = this.baseMapper.findMapBySource(filterSourceDTO);
        Map<Long, List<ApplicationFilterItem>> groupItemsMap = applicationFilterItemService.findItemByGroupIds(groupMap.keySet());

        return groupMap.values().stream().map(group -> {
            FilterGroupDTO filterGroupDTO = new FilterGroupDTO();
            filterGroupDTO.setFilterGroupId(group.getFilterGroupId());
            filterGroupDTO.setFilterGroupName(group.getFilterGroupName());
            filterGroupDTO.setFilterGroupConfig(groupItemsMap.getOrDefault(group.getFilterGroupId(), new ArrayList<>()).stream()
                    .map(FilterGroupConfigDTO::new).collect(Collectors.toList()));
            return filterGroupDTO;
        }).collect(Collectors.toList());
    }

    /**
     * 转换筛选
     *
     * @param reportingKey reportingKey
     * @param filterQuery  filterQuery
     * @return List
     */
    @Override
    public List<JudgeOr> transformFilterQuery(String reportingKey, List<FilterGroupQueryReqDTO> filterQuery) {
        List<Long> groupIds = filterQuery.stream().map(FilterGroupQueryReqDTO::getFilterGroupId).collect(Collectors.toList());

        Map<Long, ApplicationFilterGroup> groupMap = this.baseMapper.findMapByIds(groupIds);

        Map<Long, Map<Long, ApplicationFilterItem>> groupItemMap = applicationFilterItemService.findGroupItemMapByGroupIds(groupIds);
        return filterQuery.stream().map(g -> {
            if (!groupMap.containsKey(g.getFilterGroupId())) {
                throw new BusinessException(RCodeEnum.APPLICATION_FILTER_GROUP_NOT_EXIST);
            }
            // 或条件
            JudgeOr or = new JudgeOr();
            Map<Long, ApplicationFilterItem> itemMap = groupItemMap.getOrDefault(g.getFilterGroupId(), new HashMap<>());
            or.setJudgeAnd(g.getFilterGroupValue().stream().filter(i -> Objects.nonNull(i.getJudgeSign())).map(i -> {
                if (!itemMap.containsKey(i.getFilterItemId())) {
                    throw new BusinessException(RCodeEnum.APPLICATION_FILTER_ITEM_NOT_EXIST);
                }
                // 筛选项
                FilterGroupConfigDTO item = new FilterGroupConfigDTO(itemMap.get(i.getFilterItemId()));

                // 筛选项配置
                FilterConditionDTO filterConditionDTO = item.getFilterCondition().stream()
                        .filter(e -> reportingKey.equals(e.getReportingKey()))
                        .findFirst().orElseThrow(() -> new BusinessException(RCodeEnum.ERROR_PARAMETER));

                // 且条件
                JudgeAnd and = new JudgeAnd();
                and.setControlId(filterConditionDTO.getControlId());
                and.setJudgeSign(i.getJudgeSign());
                // 这里固定 字符串查询
                and.setControlCode(ControlCodeEnum.INPUT.getCode());
                and.setValues(OrderDataUtil.getOrderDataValues(i.getJudgeValue()));
                return and;
            }).collect(Collectors.toList()));

            return or;
        }).collect(Collectors.toList());
    }
}
